package com.derbysoft.synxisadapter.dswitch2.translator.impl;

import com.derbysoft.core.utils.DateTimeUtils;
import com.derbysoft.remote.dswitch.core.GenericRQ;
import com.derbysoft.remote.dswitch.hotel.dto.*;
import com.derbysoft.synxisadapter.commons.utils.Constant;
import com.derbysoft.synxisadapter.commons.model.Hotel;
import com.derbysoft.synxisadapter.commons.dto.synxis.*;
import com.derbysoft.synxisadapter.commons.exception.HotelNotFoundException;
import com.derbysoft.synxisadapter.dswitch2.translator.Translator;

import java.util.Arrays;
import java.util.List;

public class HotelAvailRQTranslatorImpl extends AbstractRQTranslator implements Translator<GenericRQ<HotelAvailRQ>, List<OTAHotelAvailRQ>, Void> {
    private static final String DATE_FORMAT = "MM/dd/yyyy";

    @Override
    public List<OTAHotelAvailRQ> translate(GenericRQ<HotelAvailRQ> from, Void param) {
        return Arrays.asList(translateOTAHotelAvailRQ(from));
    }

    private OTAHotelAvailRQ translateOTAHotelAvailRQ(GenericRQ<HotelAvailRQ> from) {
        OTAHotelAvailRQ otaHotelAvailRQ = createOTAHotelAvailRQ();
        otaHotelAvailRQ.setPrimaryLangID(Constant.PRIMARY_LANG_ID);
        otaHotelAvailRQ.setPOS(translatePOS(from.getHeader().getSource()));
        otaHotelAvailRQ.setAvailRequestSegments(translateAvailRequestSegments(from.getPayload()));
        return otaHotelAvailRQ;
    }

    private ArrayOfAvailRequestSegment translateAvailRequestSegments(HotelAvailRQ hotelAvailRQ) {
        ArrayOfAvailRequestSegment arrayOfAvailRequestSegment = createArrayOfAvailRequestSegment();
        arrayOfAvailRequestSegment.getAvailRequestSegment().add(translateAvailRequestSegment(hotelAvailRQ));
        return arrayOfAvailRequestSegment;
    }

    private AvailRequestSegment translateAvailRequestSegment(HotelAvailRQ hotelAvailRQ) {
        AvailRequestSegment availRequestSegment = createAvailRequestSegment();
        availRequestSegment.setStayDateRange(translateStayDateRange(hotelAvailRQ.getAvailCriteria().getStayDateRange()));
        availRequestSegment.setRoomStayCandidates(translateRoomStayCandidates(
            hotelAvailRQ.getAvailCriteria().getRoomStayCandidates()));
        availRequestSegment.setHotelSearchCriteria(
            translateHotelSearchCriteria(hotelAvailRQ.getAvailCriteria().getHotelRef()));
        return availRequestSegment;
    }

    private ArrayOfHotelSearchCriterion translateHotelSearchCriteria(HotelRefDTO hotelRef) {
        ArrayOfHotelSearchCriterion arrayOfHotelSearchCriterion = createArrayOfHotelSearchCriterion();
        arrayOfHotelSearchCriterion.getCriterion().add(translateCriterion(hotelRef));
        return arrayOfHotelSearchCriterion;
    }

    private HotelSearchCriterion translateCriterion(HotelRefDTO hotelRef) {
        HotelSearchCriterion criterion = createHotelSearchCriterion();
        criterion.setHotelRef(translateHotelRef(hotelRef));
        return criterion;
    }

    private HotelReferenceGroup translateHotelRef(HotelRefDTO hotelRef) {
        Hotel hotel = hotelRepository.findByPassport(hotelRef.getCode(), Hotel.Status.ENABLED);
        if (hotel == null) {
            throw new HotelNotFoundException(hotelRef.getCode());
        }
        HotelReferenceGroup hotelReferenceGroup = createHotelReferenceGroup();
        hotelReferenceGroup.setHotelCode(hotel.getId());
        return hotelReferenceGroup;
    }

    private ArrayOfRoomStayCandidate translateRoomStayCandidates(RoomStayCandidateDTO roomStayCandidateDTO) {
        ArrayOfRoomStayCandidate arrayOfRoomStayCandidate = createArrayOfRoomStayCandidate();
        arrayOfRoomStayCandidate.getRoomStayCandidate().add(translateRoomStayCandidate(roomStayCandidateDTO));
        return arrayOfRoomStayCandidate;
    }

    private RoomStayCandidate translateRoomStayCandidate(RoomStayCandidateDTO roomStayCandidateDTO) {
        RoomStayCandidate roomStayCandidate = createRoomStayCandidate();
        roomStayCandidate.setQuantity(1);
        roomStayCandidate.setGuestCounts(translateGuestCounts(roomStayCandidateDTO.getGuestCounts()));
        return roomStayCandidate;
    }

    private StayDateRangeType translateStayDateRange(StayDateRangeDTO stayDateRange) {
        StayDateRangeType stayDateRangeType = createStayDateRangeType();
        stayDateRangeType.setStart(DateTimeUtils.formatDateTime(stayDateRange.getCheckInDate(), DATE_FORMAT));
        stayDateRangeType.setEnd(DateTimeUtils.formatDateTime(stayDateRange.getCheckOutDate(), DATE_FORMAT));
        return stayDateRangeType;
    }
}
